#pragma once
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include "Sem.hpp"

#define DEFAULT_NUM 6

template <class T>
class RingQueue
{
public:
    RingQueue(int defalut_num = DEFAULT_NUM)
        : ring_queue_(defalut_num), num_(defalut_num), c_step(0), p_step(0)
        ,space_sem_(defalut_num) // 初始空间为满
        ,data_sem_(0) // data为空

    {
        pthread_mutex_init(&clock,nullptr);
        pthread_mutex_init(&plock,nullptr);
    }

    ~RingQueue()
    {
        pthread_mutex_destroy(&clock);
        pthread_mutex_destroy(&plock);
    }

    // 生产者: 空间资源  (生产者们的临界资源: 下标)
    void push(const T &in)
    {
        // 申请空间资源 -> space_sem-- 且 data_sem++ (信号量本身是原子的)
        // 先申请信号量 (多线程并发执行, 先分配完信号量) (后面就只剩进入到锁空间即可) -->效率提高
        space_sem_.p();
        //一定是竞争成功的生产者线程 -- 只有一个
        pthread_mutex_lock(&plock);
        ring_queue_[p_step++] = in;
        p_step %= num_;
        data_sem_.v();
        pthread_mutex_unlock(&plock);
    }
 
 
    // 消费者: 数据资源
    void pop(T *out)
    {
        // 申请信息资源 -> data_sem-- 且 space_sem++
        data_sem_.p();
        //一定是竞争成功的消费者线程 -- 只有一个
        pthread_mutex_lock(&clock);
        *out = ring_queue_[c_step++];
        c_step %= num_;
        space_sem_.v();
        pthread_mutex_unlock(&clock);
    }

    void debug()
    {
        std::cout << "size: " << ring_queue_.size() << " num: " << num_ << std::endl;
    }

private:
    std::vector<T> ring_queue_;
    int num_;
    int c_step; // 消费者下标
    int p_step; // 生产者下标
    Sem space_sem_;
    Sem data_sem_;
    pthread_mutex_t clock;
    pthread_mutex_t plock;
};